<?php

namespace app\common\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use app\common\service\user\UserBalanceLogService;

class DailyReward extends Command
{
    // 🔹 推荐奖励比例
    const RECOMMEND_RATES = [
        1 => 10, 2 => 5, 3 => 2, 4 => 2, 5 => 2,
        6 => 1, 7 => 1, 8 => 1, 9 => 1, 10 => 1,
    ];

    // 🔹 常量标识
    const REWARD_TYPE_RECOMMEND = 'recommended_income'; // 推荐奖励
    const REWARD_TYPE_TEAM = 'team_incentive_codex';
    const BALANCE_TYPE = 'codex';
    const REWARD_TYPE_PEER = 'peer_reward';           // 平级奖励
    const REWARD_TYPE_SURPASS = 'surpass_reward';     // 超越奖励

    protected function configure(): void
    {
        $this->setName('daily_reward')
            ->setDescription('每日奖励发放：推荐奖励 + 团队激励（独立函数版，带详细日志）');
    }

    protected function execute(Input $input, Output $output)
    {
        // $profitDate = date('Y-m-d'); // 测试用当天；上线建议改为：date('Y-m-d', strtotime('-1 day'))
        $profitDate = date('Y-m-d', strtotime('-1 day'));
        $timestamp = strtotime(date('Y-m-d'));
        $startTime = $timestamp;
        $endTime = $timestamp + 86399;

        $output->writeln("🚀 开始处理 {$profitDate} 的奖励任务...");
        $output->writeln("📅 日期范围: {$profitDate} ({$startTime} ~ {$endTime})");

        $users = Db::name('user')->where('status', 1)->select()->toArray();
        $generationsCache = []; // 缓存下级关系，避免重复递归

        foreach ($users as $user) {
            $userId = $user['id'];
            $output->writeln("\n👤 处理用户: <info>{$userId}</info>");

            // 直推多少人拿多少层级
            $level = Db::name('user')->where('pid', $user['id'])->count();

            // 🔧 获取1~10代下级（缓存避免重复计算）
            if (!isset($generationsCache[$userId])) {
                $generationsCache[$userId] = $this->getGenerationsRecursive($userId, $level);
            }
            $downlines = $generationsCache[$userId];

            if (empty($downlines)) {
                $output->writeln("  🚫 无下级，跳过");
                continue;
            } else {
                $totalMembers = array_sum(array_map('count', $downlines));
                $output->writeln("  📚 下级总数: {$totalMembers} 人，代数分布: " . json_encode(array_map('count', $downlines)));
            }

            // ✅ 执行：推荐奖励（内容铸造）
            $this->handleRecommendReward($userId, $downlines, $profitDate, $startTime, $endTime, $output);

            // ✅ 执行：团队激励奖励（所有挖矿）
            $myTeamProfit = $this->handleTeamIncentive($userId, $downlines, $profitDate, $startTime, $endTime, $output);

            // ✅ 平级 & 超越奖励
            $this->handlePeerAndSurpassRewards($userId, (float)$myTeamProfit, $profitDate, $startTime, $endTime, $output);
        }

        $output->writeln("\n✅ <info>所有奖励处理完成！</info>");
        return 0;
    }

    // ======================================================
    // 处理推荐奖励（仅 mode=2 内容铸造）
    // ======================================================
    private function handleRecommendReward(
        int    $userId,
        array  $generations,
        string $profitDate,
        int    $startTime,
        int    $endTime,
        Output $output
    )
    {
        $output->writeln("  🎁 开始计算【推荐奖励】...");

        $count = Db::name('user_investment')->where([
            'status' => 1,
            'user_id' => $userId,
            'mode' => 2
        ])->count();

        if($count <= 0){
            $output->writeln("{$userId}:没有有效用户");
            return;
        }

        $totalReward = 0.0;

        foreach ($generations as $gen => $ids) {
            $rate = self::RECOMMEND_RATES[$gen] ?? 0;
            if ($rate == 0 || empty($ids)) continue;

            $amount = Db::name('user_mining_profit_log')
                ->whereIn('user_id', $ids)
                ->where('mode', 2) // 内容铸造
                ->where('release_status', 'success')
                ->where('profit_date', $profitDate)
                ->sum('profit_amount') ?: 0.0;

            $amount = (float)$amount;
            if ($amount <= 0) {
                $output->writeln("  🟡 推荐 Gen{$gen}: 无收益，跳过");
                continue;
            }

            $reward = round($amount * ($rate / 100), 8);
            $totalReward += $reward;

            $output->writeln("  📌 Gen{$gen} 下级收益: {$amount} × {$rate}% = <comment>{$reward}</comment> CODEX");
        }

        $totalReward = round($totalReward, 8);
        if ($totalReward <= 0) {
            $output->writeln("  ⚠️ 推荐奖励合计为 0，跳过发放");
            return;
        }

        // 防重发
        $exists = $this->rewardExists($userId, self::REWARD_TYPE_RECOMMEND, $startTime, $endTime);
        if ($exists) {
            $output->writeln("  ⚠️ 推荐奖励已发放，跳过");
            return;
        }

        // 写入 cc_user_income_summary 汇总 写入cc_user_account
        Db::name('user_income_summary')->where('user_id', $userId)->inc('accumulated_referral_rewards', $totalReward)->update();
        Db::name('user_account')->where('user_id', $userId)->inc('codex_balance', $totalReward)->update();
        $this->grantReward($userId, $totalReward, self::REWARD_TYPE_RECOMMEND, "内容铸造推荐奖励", $output);
    }

    // ======================================================
    // 处理团队激励奖励（mode=1 + mode=2 所有挖矿收益）
    // ======================================================
    /**
     * @param int $userId
     * @param array $generations
     * @param string $profitDate
     * @param int $startTime
     * @param int $endTime
     * @param Output $output
     * @return float|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function handleTeamIncentive(
        int    $userId,
        array  $generations,
        string $profitDate,
        int    $startTime,
        int    $endTime,
        Output $output
    )
    {
        $output->writeln("  🛡️ 开始计算【团队激励奖励】...");

        // 获取用户等级
        $currentUser = Db::name('user')->where('id', $userId)->find();
        if (!$currentUser || empty($currentUser['level'])) {
            $output->writeln("  ❌ 用户 {$userId} 无有效等级，跳过");
            return;
        }

        $level = (int)$currentUser['level'];
        $output->writeln("  🔼 用户等级: {$level}");

        // 查询等级配置（生态奖励百分比）
        $levelConfig = Db::name('user_level')
            ->where('level', $level)
            ->where('status', 1)
            ->field('ecosystem_reward')
            ->find();

        if ($levelConfig === null) {
            $output->writeln("  ❌ 用户 {$userId} 等级 {$level} 无有效配置");
            return;
        }

        $myRate = $levelConfig['ecosystem_reward'] / 100;
        if ($myRate <= 0) {
            $output->writeln("  ⚠️ 团队激励比例为 0，跳过");
            return;
        }

        $output->writeln("  💡 查询到等级配置: 生态奖励 <comment>" . sprintf("%.2f", $myRate * 100) . "%</comment>");

        // 一级直推用户过滤等级比我大的
        // $dirUser = Db::name('user')->where('pid', $userId)->where('status', 1)->select()->toArray();
        $dirUser = Db::name('user')
            ->where('pid', $userId)
            ->where('status', 1)
//            ->where('level', '<=', $level)  // 关键：直推人等级必须低于当前用户
            ->select()
            ->toArray();
        if (empty($dirUser)) {
            $output->writeln("  🟡 无一级直推，跳过");
            return;
        }

        $output->writeln("  👤 一级直推: " . json_encode(array_column($dirUser, 'id')));

        $totalTeamProfit = 0.0;

        foreach ($dirUser as $user) {
            if($user['level'] > $level) {
                // 直推用户等级大于当前用户-拿他内容铸造收益的
                $dirUserIds = [1 => [$user['id']]];
                $output->writeln("  🧩 {$user['id']} 直推用户等级大于当前用户只能领取他自身的内容铸造收益");
            } else {
                $dirUserIds = $this->getAllGenerationsWithV0PassThrough($user['id'], $output);
            }
            $output->writeln("  🧩 {$user['id']} 的有效团队结构: " . json_encode($dirUserIds));

            // 统计该直推团队所有成员的挖矿收益（mode=1 和 mode=2）
            $allTeamMemberIds = [];
            // 🔽 先加入直推人自己
            $allTeamMemberIds[] = $user['id'];
            foreach ($dirUserIds as $gen => $ids) {
                $output->writeln("  🧩 {$user['id']} ids: " . json_encode($ids));

                $allTeamMemberIds = array_merge($allTeamMemberIds, $ids);
            }
            // 去重（防止重复用户ID）
            $allTeamMemberIds = array_unique($allTeamMemberIds);

            if (empty($allTeamMemberIds)) {
                $output->writeln("  🟡 {$user['id']} 团队无有效成员，跳过");
                continue;
            }

            $teamProfit = Db::name('user_mining_profit_log')
                ->whereIn('user_id', $allTeamMemberIds)
                ->where('mode', 2) // 内容铸造
                ->where('release_status', 'success')
                ->where('profit_date', $profitDate)
                ->sum('profit_amount') ?: 0.0;

            $teamProfit = (float)$teamProfit;
            $output->writeln("  💰 {$user['id']} 团队总收益: <comment>{$teamProfit}</comment> CODEX");

            // 当前用户收益如50% - 直推人收益如40% = 10%
            // 如果当前用户50% 直推用户50% = 50%
            if ($user['level'] != 0 && $user['level'] < $level) {
                $dirUserLevelConfig = Db::name('user_level')->where('level', $user['level'])->find();
                $dirUserRate = $dirUserLevelConfig['ecosystem_reward'] / 100;
                if ($myRate > $dirUserRate) {
                    $myRate = $myRate - $dirUserRate;
                }
            }

            // 如果直推等级大于当前用户等级 只拿他收益的10%
            if($user['level'] > $level) {
                $myRate = 0.1;
                $output->writeln("  🧩 {$user['id']} 直推用户等级大于当前用户只能领取他自身的内容铸造收益的10%");
            }

            $output->writeln("  💰 {$user['id']} 团队总收: " . $myRate . " CODEX");

            $totalTeamProfit += $teamProfit * $myRate;
        }

        $output->writeln("  📊 用户 {$userId} 的团队总收益: <info>{$totalTeamProfit}</info> CODEX");

        // 计算奖励
        $reward = round($totalTeamProfit, 8);
        if ($reward <= 0) {
            $output->writeln("  ⚠️ 计算奖励为 0，跳过发放");
            return;
        }

        $output->writeln("  🎯 应发奖励: {$reward} × {$myRate} = <info>{$reward}</info> CODEX");

        // 防重发
        $exists = $this->rewardExists($userId, self::REWARD_TYPE_TEAM, $startTime, $endTime);
        if ($exists) {
            $output->writeln("  ⚠️ 团队激励奖励已发放，跳过");
            return;
        }

        // 写入 cc_user_income_summary 汇总 写入cc_user_account
        Db::name('user_income_summary')->where('user_id', $userId)->inc('accumulated_team_rewards', $reward)->update();
        Db::name('user_account')->where('user_id', $userId)->inc('codex_balance', $reward)->update();

        // 发放奖励
        $this->grantReward($userId, $reward, self::REWARD_TYPE_TEAM, "团队激励奖励", $output);
        // ✅ 新增：返回团队总收益（用于平级/超越奖励）
        return $totalTeamProfit; // 👈 就加这一行
    }

    // ======================================================
    // 处理平级奖励 & 超越奖励（精准版）
    // ======================================================
    /**
     * 处理平级奖励 和 超越奖励
     *
     * @param int $userId
     * @param float $myTeamProfit
     * @param string $profitDate
     * @param int $startTime
     * @param int $endTime
     * @param Output $output
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function handlePeerAndSurpassRewards(
        int    $userId,           // 当前用户（下级）
        float  $myTeamProfit,     // 当前用户的团队总收益（用于计算奖励）
        string $profitDate,
        int    $startTime,
        int    $endTime,
        Output $output
    )
    {

        $output->writeln("  🌟 开始处理【平级 & 超越奖励】...");

        // 获取当前用户
        $user = Db::name('user')->where('id', $userId)->field('id,pid,level')->find();
        if (!$user || empty($user['pid'])) {
            $output->writeln("  🚫 用户 {$userId} 无上级，跳过");
            return;
        }


        $currentLevel = (int)$user['level'];
        $parentId = (int)$user['pid'];

        // 获取上级
        $parent = Db::name('user')->where('id', $parentId)->field('id,level')->find();
        if (!$parent) {
            $output->writeln("  ❌ 上级 {$parentId} 不存在");
            return;
        }

        $parentLevel = (int)$parent['level'];

        $dirUserIds = Db::name('user')->where('path', 'like', '%,' . $userId . ',%')->column('id');
        $myTeamProfit = Db::name('user_mining_profit_log')
            ->where('mode', 2)
            ->where('release_status', 'success')
            ->where('profit_date', $profitDate)
            ->whereIn('user_id', $dirUserIds)->sum('profit_amount');

        // ========== 1. 平级奖励：当前用户 level == 上级 level ==========
        if ($currentLevel === $parentLevel && $currentLevel > 0) {
            $peerReward = round($myTeamProfit * 0.1, 8); // 10%

            if ($peerReward > 0) {
                $exists = $this->rewardExists($parentId, self::REWARD_TYPE_PEER, $startTime, $endTime);

                if (!$exists) {
                    // 写入 cc_user_income_summary 汇总 写入cc_user_account
                    Db::name('user_income_summary')->where('user_id', $parentId)->inc('total_peer_level_rewards', $peerReward)->update();
                    Db::name('user_account')->where('user_id', $parentId)->inc('codex_balance', $peerReward)->update();
                    $this->grantReward($parentId, $peerReward, 'peer_reward', "平级奖励（来自下级 {$userId}）", $output);
                    $output->writeln("  🎁 平级奖励发放: <info>{$peerReward}</info> CODEX → 上级 [{$parentId}]");
                } else {
                    $output->writeln("  ⚠️ 平级奖励已发放，跳过 [{$parentId}]");
                }
            }
        }


        // ========== 2. 超越奖励：逐级向上穿透发放 ==========
        // ✅ 关键修正：必须确保【直推上级】是非 V0 且等级低于当前用户，才启动超越奖励
        if ($currentLevel > 0 && $parentLevel > 0 && $currentLevel > $parentLevel) {
            $currentPid = $parentId; // 从直推上级开始
            $prevReward = 0.0;
            $generation = 0;

            while ($currentPid > 0) {
                $ancestor = Db::name('user')->where('id', $currentPid)->field('id,pid,level')->find();
                if (!$ancestor) break;

                $ancId = (int)$ancestor['id'];
                $ancLevel = (int)$ancestor['level'];
                $ancPid = (int)$ancestor['pid'];

                // ✅ STEP 1: 如果是 V0，跳过，继续向上（仅作为通道）
                if ($ancLevel == 0) {
                    $output->writeln("  ⚪ 跳过 V0 用户 [{$ancId}]，继续向上查找");
                    $currentPid = $ancPid;
                    continue;
                }

                // ✅ STEP 2: 非 V0 用户，判断是否等级压制（>= 当前用户 level）
                if ($ancLevel >= $currentLevel) {
                    $output->writeln("  🔴 【停止】遇到非V0且 level >= {$currentLevel} 的用户 [{$ancId}]，终止超越奖励");
                    break;
                }

                // ✅ STEP 3: 满足条件，发放奖励
                $rewardAmount = ($generation === 0)
                    ? round($myTeamProfit * 0.1, 8)
                    : round($prevReward * 0.1, 8);

                $desc = ($generation === 0)
                    ? "超越奖励 - 第1级（来自下级 {$userId}）"
                    : "超越奖励 - 第" . ($generation + 1) . "级（传承）";

                // 🔒 防重发
                $exists = $this->rewardExists($ancId, self::REWARD_TYPE_SURPASS, $startTime, $endTime);

                if ($rewardAmount > 0 && !$exists) {
                    // 写入 cc_user_income_summary 汇总 写入cc_user_account
                    Db::name('user_income_summary')->where('user_id', $userId)->inc('total_surpass_reward_rewards', $rewardAmount)->update();
                    Db::name('user_account')->where('user_id', $userId)->inc('codex_balance', $rewardAmount)->update();
                    $this->grantReward($ancId, $rewardAmount, 'surpass_reward', $desc, $output);
                    $output->writeln("  🚀 超越奖励发放: <info>{$rewardAmount}</info> CODEX → 用户 [{$ancId}] (level={$ancLevel}, 第" . ($generation + 1) . "级)");
                } elseif ($exists) {
                    $output->writeln("  ⚠️ 超越奖励已发放，跳过 [{$ancId}]");
                } else {
                    $output->writeln("  ⚠️ 奖励金额为0，跳过 [{$ancId}]");
                }

                $prevReward = $rewardAmount;
                $generation++;
                $currentPid = $ancPid;
            }

            if ($generation === 0) {
                $output->writeln("  🟡 未找到任何符合条件的超越奖励接收者");
            }
        } else {
            // ✅ 明确说明不触发原因
            if ($parentLevel == 0) {
                $output->writeln("  🟡 直推上级为 V0（level=0），不触发超越奖励机制");
            } elseif ($parentLevel >= $currentLevel) {
                $output->writeln("  🟡 直推上级 level({$parentLevel}) >= 当前用户 level({$currentLevel})，不触发超越奖励");
            } else {
                $output->writeln("  🟡 未知原因未触发超越奖励");
            }
        }
    }

    // ======================================================
    // 获取穿透团队（V0用户继承上级压制等级）
    // ======================================================
    private function getAllGenerationsWithV0PassThrough(int $userId, $output = null): array
    {
        $user = Db::name('user')->where('id', $userId)->field('level')->find();
        if (!$user) {
            $output?->writeln("  ❌ 未找到用户 {$userId}");
            return [];
        }

        $initialSupervisorLevel = (int)$user['level'];
        $output?->writeln("    🔍 分析穿透团队: 用户={$userId}, 初始压制等级={$initialSupervisorLevel}");

        $allDownlines = Db::name('user')
            ->where('path', 'like', "%,{$userId},%")
            ->where('id', '<>', $userId)
            ->where('status', 1)
            ->field('id, level, path')
            ->order('path')
            ->select()
            ->toArray();

        if (empty($allDownlines)) {
            $output?->writeln("    🟡 无下级成员");
            return [];
        }

        $result = [];
        $supervisorMap = [$userId => $initialSupervisorLevel];

        foreach ($allDownlines as $downline) {
            $downlineId = (int)$downline['id'];
            $downlineLevel = (int)$downline['level'];
            $path = trim($downline['path'], ", \t\n\r\0\x0B");

            // ✅ 关键修复：重置索引，确保路径正确
            $pathIds = array_values(array_filter(explode(',', $path), 'strlen'));

            $output?->writeln("      ➡️ 成员 ID={$downlineId}, Level={$downlineLevel}, Path=" . json_encode($pathIds));

            if (count($pathIds) < 2) {
                $output?->writeln("        ⚠️ 路径太短，跳过");
                continue;
            }

            $parentIndex = count($pathIds) - 2;
            $parentId = (int)$pathIds[$parentIndex];
            if ($parentId <= 0) {
                $output?->writeln("        ⚠️ 父ID无效，跳过");
                continue;
            }

            $parentSupervisorLevel = $supervisorMap[$parentId] ?? null;
            if ($parentSupervisorLevel === null) {
                $output?->writeln("        ⚠️ 父级 {$parentId} 无压制等级，跳过");
                continue;
            }

            $thisSupervisorLevel = $downlineLevel > 0 ? $downlineLevel : $parentSupervisorLevel;
            $output?->writeln("        🔒 压制等级: 父{$parentSupervisorLevel} → 当前{$thisSupervisorLevel}");

            if ($downlineLevel > $parentSupervisorLevel) {
                $output?->writeln("        ❌ 断层: {$downlineLevel} > {$parentSupervisorLevel}，不计入");
                continue;
            }

            $userPos = array_search((string)$userId, $pathIds, true);
            if ($userPos === false) {
                $output?->writeln("        ❌ 路径中未找到 {$userId}，跳过");
                continue;
            }

            $depth = count($pathIds) - $userPos - 1;
            if ($depth < 1) {
                $output?->writeln("        ⚠️ 代数计算异常: depth={$depth}");
                continue;
            }

            $result[$depth][] = $downlineId;
            $supervisorMap[$downlineId] = $thisSupervisorLevel;

            $output?->writeln("        ✅ 加入第 {$depth} 代，当前: " . json_encode($result[$depth] ?? []));
        }

        ksort($result);
        $output?->writeln("    🏁 最终穿透团队: " . json_encode($result));
        return $result;
    }

    // ======================================================
    // 公共方法：检查是否已发放
    // ======================================================
    private function rewardExists(int $userId, string $bizType, int $startTime, int $endTime): bool
    {
        return (bool)Db::name('user_balance_log')
            ->where('user_id', $userId)
            ->where('biz_type', $bizType)
            ->where('create_time', '>=', $startTime)
            ->where('create_time', '<=', $endTime)
            ->find();
    }

    // ======================================================
    // 公共方法：执行发币
    // ======================================================
    private function grantReward(
        int    $userId,
        float  $amount,
        string $bizType,
        string $title,
        Output $output
    )
    {
        $output->writeln("  💸 准备发放奖励: <info>{$amount}</info> CODEX, 类型: {$bizType}");

        try {
            $service = app()->make(UserBalanceLogService::class);
            $result = $service->addLog(
                $userId,
                $bizType,
                self::BALANCE_TYPE,
                $amount,
                "{$title} (" . date('Y-m-d') . ")",
                "获得奖励: {$amount} CODEX",
                'increase'
            );

            if ($result) {
                $output->writeln("  ✅ <info>成功发放 {$amount} CODEX [{$bizType}]</info>");
            } else {
                $output->writeln("  ❌ 发放失败: {$bizType}");
            }
        } catch (\Exception $e) {
            $output->writeln("  ❌ 发放异常 [{$bizType}]: " . $e->getMessage());
            $output->writeln("  🧾 错误行: " . $e->getLine());
        }
    }

    // ======================================================
    // 递归获取N代下级（用于推荐奖励）
    // ======================================================
    private function getGenerationsRecursive(int $userId, int $maxDepth, int $level = 1): array
    {
        if ($level > $maxDepth) return [];
        $children = Db::name('user')
            ->where('pid', $userId)
            ->where('status', 1)
            ->column('id');
        if (empty($children)) return [];

        $result = [$level => $children];
        foreach ($children as $id) {
            $sub = $this->getGenerationsRecursive($id, $maxDepth, $level + 1);
            foreach ($sub as $g => $list) {
                $result[$g] = array_merge($result[$g] ?? [], $list);
            }
        }
        return $result;
    }
}